﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Drawing;

namespace DirectX_CS
{
    public delegate float CartesianZFunc(float x, float y);

    public class Simple3dRectangle : IManagedVertexBuffer, IManagedMaterial, IManagedModelTransformable, IColorable, IRangeModifiable	, IDisposable
	{
		[PGBrowsable]
		public Range3d Range
		{
			get { return new Range3d(XMin, YMin, ZMin, XMax, YMax, ZMax); }
		}
		float mZMin = -10, mZMax = 10; //should be maximum and mimum of the function though... in the future.
		[PGBrowsable]
		public float ZMin
		{
			get { return mZMin; }
			set { mZMin = value; }
		}
		[PGBrowsable]
		public float ZMax
		{
			get { return mZMax; }
			set { mZMax = value; }
		}

        private CartesianZFunc mPlaneZFunc = null;
 
        public event VBChangedDelegate VertexBufferChanged;

        protected PrimitiveManager renderer = null; //main memory manager..change name.
        protected Device mDevice = null;
        protected SVector[] vertexData = null;
		[PGBrowsable]
		public VertexFormats VertexFormat
		{
			get { return SVector.Format; }
		}
		protected bool mEnableCallRenderPrimitives = true;
		[PGBrowsable]
		public bool EnableCallRenderPrimitives
		{
			get { return mEnableCallRenderPrimitives; }
			set { mEnableCallRenderPrimitives = value; }
		}
		protected bool mEnableCallRenderIndexedPrimitives = true;
		[PGBrowsable]
		public bool EnableCallRenderIndexedPrimitives
		{
			get { return mEnableCallRenderIndexedPrimitives; }
			set { mEnableCallRenderIndexedPrimitives = value; }
		}

        float xMin = 0, xMax = 10;
        float yMin = 0, yMax = 10;
        protected Material mMaterial;
		[PGBrowsable]
		public Material Material
        {
			get { return mMaterial; }
			set { mMaterial = value; }
        }
        protected void InitializeMaterial()
        {
            //Color c = Color.OrangeRed;
            mMaterial = new Material();
            mMaterial.Specular = Color.FromArgb(122,255,255,255);
            mMaterial.Ambient = Color.FromArgb(122,255,255,255);
            mMaterial.Diffuse = Color.FromArgb(122,255,255,255);
        }

		Color mMainVertexColor = Color.Navy;
		[PGBrowsable]
		public Color MainVertexColor
		{
			get { return mMainVertexColor; }
			set { mMainVertexColor = value; }
		}

        public static float DefaultPlaneZFunc(float x, float y)
        {
            return 0;

        }
		public Simple3dRectangle()//, Cartesian3dSurface matchDataObject)
		{
			mPlaneZFunc = DefaultPlaneZFunc;
			CreateVertexData();
			renderer = PrimitiveManager.OnlyManager;
			mDevice = MainProgram.DxDevice; //set before registering for sure...
			InitializeMaterial();
			PrimitiveManager.Register(this);
			VertexBufferChanged(this, vertexData.Length); //as soon as its registered calls will probably start arriving.
		}

        public Simple3dRectangle(CartesianZFunc PlaneZFunc, float xmin, float xmax, float ymin, float ymax)//, Cartesian3dSurface matchDataObject)
        {
			this.xMin = xmin; this.xMax = xmax;
			this.yMin = ymin; this.yMax = ymax;
            mPlaneZFunc = PlaneZFunc;
            CreateVertexData();
            renderer = PrimitiveManager.OnlyManager;
            mDevice = MainProgram.DxDevice; //set before registering for sure...
            InitializeMaterial();
            PrimitiveManager.Register(this);
            if (VertexBufferChanged != null)
                VertexBufferChanged(this, vertexData.Length); //as soon as its registered calls will probably start arriving.
        }

		public void Recreate ()
		{
            CreateVertexData();
            if (VertexBufferChanged != null)
                VertexBufferChanged(this, vertexData.Length); //as soon as its registered calls will probably start arriving.
        }
		public void UpdateTransform()
		{
			VertexBufferChanged(this, vertexData.Length); //as soon as its registered calls will probably start arriving.
		}
        ~Simple3dRectangle()
        {
			DisposeInstance();
        }

		public void DisposeInstance()
		{
			if (renderer != null)
				renderer.UnregisterPrimitive(this); //cannot hurt to unregister.
		}

        public void CreateVertexData()
        {
			int color = mMainVertexColor.ToArgb();
            vertexData = new SVector[4]; //using a triangle list with 2 triangles (primitives) at 3 verts each
            vertexData[0].X = xMin;
            vertexData[0].Y = yMin; 
            vertexData[0].Z = DefaultPlaneZFunc(vertexData[0].X, vertexData[0].Y);
			vertexData[0].Color = color;

            vertexData[1].X = xMax; 
            vertexData[1].Y = yMin; 
            vertexData[1].Z = DefaultPlaneZFunc(vertexData[1].X, vertexData[0].Y);
			vertexData[1].Color = color;

            vertexData[2].X = xMin; 
            vertexData[2].Y = yMax; 
            vertexData[2].Z = DefaultPlaneZFunc(vertexData[2].X, vertexData[0].Y);
			vertexData[2].Color = color;

            vertexData[3].X = xMax;
            vertexData[3].Y = yMax; 
            vertexData[3].Z = DefaultPlaneZFunc(vertexData[3].X, vertexData[0].Y);
			vertexData[3].Color = color;
        }
		[PGBrowsable]
        public float XMin
        {
            get { return xMin; }
            set
            {
                xMin = value; 
            }
        }
		[PGBrowsable]
        public float XMax
        {
            get { return xMax; }
            set
            {
                xMax = value; 
            }
		}
		[PGBrowsable]
        public float YMin
        {
            get { return yMin; }
            set
            {
                yMin = value;
            }
        }
		[PGBrowsable]
        public float YMax
        {
            get { return yMax; }
            set
            {
                yMax = value; 
            }
        }

		public Array GetVertices()
        {
			return (Array)vertexData;
        }

        public int GetVerticesCount()
        {
            return vertexData.Length;
        }

        /// <summary>
        /// Since each primitiveWithVertices should for diversity be in charge of its own representation
        /// in rendering, although the memory will be managed.
        /// </summary>
        public void RenderPrimitives(PrimitiveManager caller, int dataLength)
        {
                mDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
        }

        long[] GetIndices()
        {
            return null;
        }

        public void ManagerDestroyed(PrimitiveManager caller)
        {
            //signals to registered primitiveWithVertices generator that renderer is or has been destroyed
            //so we should stop sending messages or at least relaying them to the renderer
            renderer = null;
        }

		private TransformMatrix modelView = new TransformMatrix();
		[PGBrowsable]
		public TransformMatrix ModelView
		{
			get { return modelView; }
			set { modelView = value; }
		}


    }//end of class..
}//end of namespace.
